 {*****************************Version: MPL 1.1*********************************
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * Initial Developer : Fajar Khairil
 *
 * Portions created by the Initial Developer are Copyright (C) 2010 - 2011
 * the Initial Developer. All Rights Reserved.
 *
 *******************************************************************************
 * This File is Part of HdFramework OPF Library
 * Copyright (C) 2010 - 2011 HdFramework Developer Team
 *
 * Unit : hade.opf.OID
 * Description : OID Generator using GUID(Global Unique IDentifier).
 *
 * Author: - Fajar Khairil
 ******************************************************************************}

unit hadeOID;

{$mode objfpc}{$H+}

interface

uses
  classes,
  SysUtils,
  hadeopfmanager,
  hadebaseobject;

type

  { THdOID }

  THdOID = interface
  ['{719BAD53-B8E1-4319-8846-17B5A76C27A3}']
    function getGUID:String;
    function getInteger:Int64;
    procedure setInteger(AValue:int64);
    procedure setGUID(AValue:String);

    function getValue:Variant;

    procedure setOIDValue(const AValue: variant);

    property StringOID:string read getGUID write setGUID;
    property IntegerOID:int64 read getInteger write setInteger;
    property ValueOID:variant read getValue write setOIDValue;

    function isNUll:Boolean;
  end;

  { THadeBaseOID }

  THadeBaseOID = class(THadeBaseObject,THdOID)
  public
    function getGUID:String;virtual;
    function getInteger:Int64;virtual;
    procedure setInteger(AValue:int64);virtual;
    procedure setGUID(AValue:String);virtual;

    procedure setOIDValue(const AValue: variant);virtual;
    function getValue:Variant; virtual;

    function isNUll:Boolean;virtual;
  end;

  { THadeOIDGUID }

  THadeOIDGUID = class(THadeBaseOID)
  private
    FOID:String;
  protected
    function NewOID:String;
  public
    constructor create(AValue:String='');

    function getGUID:String;override;
    function getInteger:Int64;override;
    procedure setInteger(AValue:int64);override;
    procedure setGUID(AValue:String);override;
    procedure setOIDValue(const AValue: variant);override;

    function getValue:Variant;override;

    function isNUll:Boolean;override;
  end;

  { THadeOIDAutoInc }

  THadeOIDAutoInc = class(THadeBaseOID)
  private
    FOID:Int64;
  public
    function getInteger:Int64;override;
    function getGUID:String;override;
    procedure setInteger(AValue:int64);override;
    procedure setGUID(AValue:String);override;
    function isNUll:Boolean;override;

    procedure setOIDValue(const AValue: variant);override;
    function getValue:Variant; override;

    constructor create(AValue:int64 = 0);
  end;

  { THadeOIDUserDefined }

  THadeOIDUserDefined = class(THadeBaseOID)
  private
    fOID:Variant;
  public
    function getGUID:String;override;
    function getInteger:Int64;override;
    procedure setInteger(AValue:int64);override;
    procedure setGUID(AValue:String);override;

    procedure setOIDValue(const AValue: variant);override;
    function getValue:Variant;override;

    function isNUll:Boolean;override;
  end;

  { TOIDGenerator }
  //Factory
  TOIDGenerator = class
  public
    function getOID : THdOID;
  end;

function GHadeOID: TOIDGenerator;

implementation
uses
  variants;
var
  FHdOID: TOIDGenerator = nil;

function GHadeOID: TOIDGenerator;
begin
  if not Assigned(FHdOID) then
    FHdOID := TOIDGenerator.Create;
  Result := FHdOID;
end;

{ THadeBaseOID }

function THadeBaseOID.getGUID: String;
begin

end;

function THadeBaseOID.getInteger: Int64;
begin

end;

procedure THadeBaseOID.setInteger(AValue: int64);
begin

end;

procedure THadeBaseOID.setGUID(AValue: String);
begin

end;

procedure THadeBaseOID.setOIDValue(const AValue: variant);
begin

end;

function THadeBaseOID.getValue: Variant;
begin

end;

function THadeBaseOID.isNUll: Boolean;
begin

end;

{ THadeOIDUserDefined }

function THadeOIDUserDefined.getGUID: String;
begin
  Result := varToStr(fOID);
end;

function THadeOIDUserDefined.getInteger: Int64;
begin
  Result := fOID;
end;

procedure THadeOIDUserDefined.setInteger(AValue: int64);
begin
  fOID:=AValue;
end;

procedure THadeOIDUserDefined.setGUID(AValue: String);
begin
  fOID:=AValue;
end;

procedure THadeOIDUserDefined.setOIDValue(const AValue: variant);
begin
  fOID:=AValue;
end;

function THadeOIDUserDefined.getValue: Variant;
begin
  Result:=fOID;
end;

function THadeOIDUserDefined.isNUll: Boolean;
begin
  Result := fOID = NULL;
end;

{ THadeOIDAutoInc }

function THadeOIDAutoInc.getInteger: Int64;
begin
  Result:=FOID;
end;

function THadeOIDAutoInc.getGUID: String;
begin
  if FOID <= 0 then
    Result:='NULL'
  else
    Result:=intToStr(FOID);
end;

procedure THadeOIDAutoInc.setInteger(AValue: int64);
begin
  FOID:=AValue;
end;

procedure THadeOIDAutoInc.setGUID(AValue: String);
begin
  FOID:=StrToInt(AValue);
end;

function THadeOIDAutoInc.isNUll: Boolean;
begin
  Result:= FOID <= 0;
end;

procedure THadeOIDAutoInc.setOIDValue(const AValue: variant);
var
  tmp: int64;
begin
  if AValue = NULL then
  begin
    setInteger(0);
    exit;
  end;
  tmp := StrToInt64Def(AValue,0);
  if (tmp <> 0) then
    setInteger(tmp);
end;

function THadeOIDAutoInc.getValue: Variant;
begin
  if IsNULL then
    Result := NULL
  else
    Result := foid;
end;

constructor THadeOIDAutoInc.create(AValue: int64);
begin
  FOID:=AValue;
end;

{ TOIDGenerator }

function TOIDGenerator.getOID: THdOID;
begin
  Case GHadeOPFManager.OIDStrategy of
  oidGUID : Result:= THadeOIDGUID.Create();
  oidAutoInc :Result:= THadeOIDAutoInc.Create();
  oidUserDefined : Result := THadeOIDUserDefined.Create;
  else
    Result:= THadeOIDAutoInc.Create();
  end;
end;

{ THadeOIDGUID }

function THadeOIDGUID.NewOID: string;
var
  lGUID: TGUID;
  LValue: string;
const
  cGUIDLength = 38;
begin
  CreateGUID(lGUID);
  LValue := GUIDToString(lGUID);
  if (LValue[1] = '{') and (LValue[cGUIDLength] = '}') then
    LValue := Copy(lValue, 2, cGUIDLength - 2);
  Result := LValue;
end;

constructor THadeOIDGUID.create(AValue: String);
begin
  FOID:=AValue;
end;

function THadeOIDGUID.getGUID: String;
begin
  if Length(FOID) = 0 then
    FOID:=self.NewOID;
  Result := FOID;
end;

function THadeOIDGUID.getInteger: Int64;
begin
  Result:=0;
end;

procedure THadeOIDGUID.setInteger(AValue: int64);
begin

end;

procedure THadeOIDGUID.setGUID(AValue: String);
begin
  FOID:=AValue;
end;

procedure THadeOIDGUID.setOIDValue(const AValue: variant);
var
  tmp: string;
begin
  if AValue = NULL then
  begin
    setGUID('');
    exit;
  end;

  tmp := varToStr(AValue);
  if (trim(tmp) <> '') or (trim(tmp) <> '0') then
    setGUID(tmp);
end;

function THadeOIDGUID.getValue: Variant;
begin
  if IsNULL then
    Result := NULL
  else
    Result := foid;
end;

function THadeOIDGUID.isNUll: Boolean;
begin
  Result:= FOID = '';
end;

finalization
  if Assigned(FHdOID) then
    FreeAndNil(FHdOID);

end.

